package org.dromara.genealogy.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.idev.excel.util.ListUtils;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.compress.utils.Lists;
import org.dromara.common.core.constant.SystemConstants;
import org.dromara.common.core.enums.genStatus;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.ObjectUtils;
import org.dromara.common.core.utils.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.utils.TreeBuildUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.genealogy.domain.GeDirectory;
import org.dromara.genealogy.domain.bo.GeDirectoryBo;
import org.dromara.genealogy.domain.bo.GeNameChildrenBo;
import org.dromara.genealogy.domain.vo.GeNameTranVo;
import org.dromara.genealogy.domain.vo.NameTreeVo;
import org.dromara.system.domain.vo.SysUserVo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.dromara.genealogy.domain.bo.GeNameBo;
import org.dromara.genealogy.domain.vo.GeNameVo;
import org.dromara.genealogy.domain.GeName;
import org.dromara.genealogy.mapper.GeNameMapper;
import org.dromara.genealogy.service.IGeNameService;

import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.stream.Collectors;

/**
 * 世代名称Service业务层处理
 *
 * @author qianjm
 * @date 2025-09-04
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class GeNameServiceImpl implements IGeNameService {

    private final GeNameMapper baseMapper;

    @Value("${file.baseUrl}")
    private String baseUrl;

    /**
     * 查询世代名称
     *
     * @param id 主键
     * @return 世代名称
     */
    @Override
    public GeNameVo queryById(Long id){
        GeNameVo vo = baseMapper.selectVoById(id);
        //获取孩子节点
        List<GeNameVo> childrenList = baseMapper.selectVoList(Wrappers.<GeName>lambdaQuery().eq(GeName::getParentId, id).isNull(GeName::getOtherId));
        vo.setSonNum((int)childrenList.stream().filter(x -> "0".equals(x.getGender())).count());
        vo.setDaughterNum((int)childrenList.stream().filter(x -> "1".equals(x.getGender())).count());
        vo.setChildrenList(childrenList);
        //获取妻子数据
        List<GeNameVo> wifeList = baseMapper.selectVoList(Wrappers.<GeName>lambdaQuery().eq(GeName::getOtherId, id));
        vo.setWifeList(wifeList);
        return vo;
    }

    /**
     * 查询世代名称
     *
     * @param id 主键
     * @return 世代名称
     */
    @Override
    public GeNameTranVo queryTransById(Long id){
        GeName geName = baseMapper.selectById(id);
        GeNameTranVo vo = null;
        if(ObjectUtils.isNotNull(geName)){
            vo = MapstructUtils.convert(geName, GeNameTranVo.class);
            //获取孩子节点
            List<GeName> childrenList = baseMapper.selectList(Wrappers.<GeName>lambdaQuery().eq(GeName::getParentId, id).isNull(GeName::getOtherId));
            vo.setSonNum((int)childrenList.stream().filter(x -> "0".equals(x.getGender())).count());
            vo.setDaughterNum((int)childrenList.stream().filter(x -> "1".equals(x.getGender())).count());
            vo.setChildrenList(MapstructUtils.convert(childrenList, GeNameTranVo.class));
            //获取妻子数据
            List<GeName> wifeList = baseMapper.selectList(Wrappers.<GeName>lambdaQuery().eq(GeName::getOtherId, id));
            vo.setWifeList(MapstructUtils.convert(wifeList, GeNameTranVo.class));
        }
        return vo;
    }


    /**
     * 查询符合条件的世代名称列表
     *
     * @param bo 查询条件
     * @return 世代名称列表
     */
    @Override
    public List<GeNameVo> queryList(GeNameBo bo) {
        LambdaQueryWrapper<GeName> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    @Override
    public List<GeNameTranVo> queryListTran(GeNameBo bo) {
        LambdaQueryWrapper<GeName> lqw = buildQueryWrapper(bo);
        List<GeName> list = baseMapper.selectList(lqw);
        List<GeNameTranVo> tranVos = ListUtils.newArrayList();
        if(CollUtil.isNotEmpty(list)){
            tranVos = list.stream().map(x -> MapstructUtils.convert(x, GeNameTranVo.class)).collect(Collectors.toList());
        }
        return tranVos;
    }

    @Override
    public Page<GeNameVo> selectPageNameList(GeNameBo bo, PageQuery pageQuery) {
        Page<GeNameVo> page = baseMapper.selectPageNameList(pageQuery.build(), this.buildQueryWrapper(bo));
        return page;
    }

    private LambdaQueryWrapper<GeName> buildQueryWrapper(GeNameBo bo) {
        //Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<GeName> lqw = Wrappers.lambdaQuery();
        lqw.orderByAsc(GeName::getGeneName);
        lqw.isNull(GeName::getOtherId);
        lqw.ge(bo.getGeneName() != null, GeName::getGeneName, bo.getGeneName());
        lqw.like(StringUtils.isNotBlank(bo.getName()), GeName::getName, bo.getName());
        lqw.like(StringUtils.isNotBlank(bo.getLastName()), GeName::getLastName, bo.getLastName());
        lqw.like(StringUtils.isNotBlank(bo.getCommonName()), GeName::getCommonName, bo.getCommonName());
        lqw.eq(StringUtils.isNotBlank(bo.getAlias()), GeName::getAlias, bo.getAlias());
        lqw.eq(StringUtils.isNotBlank(bo.getMark()), GeName::getMark, bo.getMark());
        lqw.eq(bo.getParentId() != null, GeName::getParentId, bo.getParentId());
        lqw.eq(StringUtils.isNotBlank(bo.getRelation()), GeName::getRelation, bo.getRelation());
        lqw.like(StringUtils.isNotBlank(bo.getParentName()), GeName::getParentName, bo.getParentName());
        lqw.eq(StringUtils.isNotBlank(bo.getRankNo()), GeName::getRankNo, bo.getRankNo());
        lqw.eq(StringUtils.isNotBlank(bo.getSchool()), GeName::getSchool, bo.getSchool());
        lqw.eq(StringUtils.isNotBlank(bo.getProfessional()), GeName::getProfessional, bo.getProfessional());
        lqw.eq(StringUtils.isNotBlank(bo.getDegree()), GeName::getDegree, bo.getDegree());
        lqw.eq(StringUtils.isNotBlank(bo.getGender()), GeName::getGender, bo.getGender());
        lqw.eq(StringUtils.isNotBlank(bo.getDuties()), GeName::getDuties, bo.getDuties());
        lqw.eq(StringUtils.isNotBlank(bo.getTitle()), GeName::getTitle, bo.getTitle());
        lqw.eq(bo.getBirthday()!=null, GeName::getBirthday, bo.getBirthday());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), GeName::getStatus, bo.getStatus());
        lqw.eq(bo.getDeadTime()!=null, GeName::getDeadTime, bo.getDeadTime());
        lqw.eq(StringUtils.isNotBlank(bo.getBurialSite()), GeName::getBurialSite, bo.getBurialSite());
        lqw.eq(StringUtils.isNotBlank(bo.getPersonType()), GeName::getPersonType, bo.getPersonType());
        lqw.eq(bo.getOtherId() != null, GeName::getOtherId, bo.getOtherId());
        lqw.eq(bo.getGeId() != null, GeName::getGeId, bo.getGeId());
        lqw.and(StringUtils.isNotBlank(bo.getKeyWord()),q -> q.like(GeName::getLastName, bo.getKeyWord()).or().like(GeName::getGeneName, bo.getKeyWord()).or().like(GeName::getCommonName, bo.getKeyWord()));
        return lqw;
    }

    /**
     * 新增世代名称
     *
     * @param bo 世代名称
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(GeNameBo bo) {
        GeName add = MapstructUtils.convert(bo, GeName.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        saveChildAndWife(bo);
        return flag;
    }

    /**
     * 保存子女和妻子数据
     * @param bo
     */
    private void saveChildAndWife(GeNameBo bo) {
        //子表数据新增和修改
        List<GeNameBo> childrenBoList = bo.getChildrenList();
        List<GeName> childrenList = CollUtil.newArrayList();
        if(CollUtil.isNotEmpty(childrenBoList)){
            childrenBoList.forEach(x -> {
                x.setParentId(bo.getId());
                GeName child = MapstructUtils.convert(x, GeName.class);
                //判断如果id为空则设置世代
                if(x.getId()==null){
                    child.setName(bo.getName());
                    child.setGeneName(bo.getGeneName()+1);
                    child.setCommonName(bo.getName()+ bo.getLastName());
                    child.setStatus(genStatus.NORMAL.getCode());
                }
                childrenList.add(child);
            });
        }
        baseMapper.insertOrUpdateBatch(childrenList);
        //保存妻子数据
        List<GeNameBo> wifeBoList = bo.getWifeList();
        List<GeName> wifeList = CollUtil.newArrayList();
        if(CollUtil.isNotEmpty(wifeBoList)){
            wifeBoList.forEach(x -> {
                x.setParentId(bo.getId());
                GeName wife = MapstructUtils.convert(x, GeName.class);
                //判断如果id为空则设置世代
                if(x.getId()==null){
                    wife.setName(bo.getName());
                    wife.setGeneName(bo.getGeneName()+1);
                    wife.setCommonName(bo.getName()+ bo.getLastName());
                    wife.setStatus(genStatus.NORMAL.getCode());
                    wife.setOtherId(bo.getId());
                }
                wifeList.add(wife);
            });
        }
        baseMapper.insertOrUpdateBatch(wifeList);
    }

    /**
     * 修改世代名称
     *
     * @param bo 世代名称
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(GeNameBo bo) {
        GeName update = MapstructUtils.convert(bo, GeName.class);
        validEntityBeforeSave(update);
        boolean flag = baseMapper.updateById(update) > 0;
        saveChildAndWife(bo);
        return flag;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(GeName entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 校验并批量删除世代名称信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteByIds(ids) > 0;
    }

    /**
     * 查询族谱族员树结构信息
     *
     * @param bo 族员信息
     * @return 族员树信息集合
     */
    @Override
    public List<Tree<Long>> genealogyNameTreeList(GeNameBo bo) {
        LambdaQueryWrapper<GeName> lqw = buildQueryWrapper(bo);
        List<GeName> list = baseMapper.selectList(lqw);
        return buildTreeSelect(list);
    }

    /**
     * 构建前端所需要下拉树结构
     *
     * @param nameList 目录列表
     * @return 下拉树结构列表
     */
    @Override
    public List<Tree<Long>> buildTreeSelect(List<GeName> nameList) {
        if (CollUtil.isEmpty(nameList)) {
            return CollUtil.newArrayList();
        }
        return TreeBuildUtils.buildMultiRoot(
            nameList,
            GeName::getId,
            GeName::getParentId,
            (node, treeNode) ->{
                treeNode.setId(node.getId())
                    .setParentId(node.getParentId())
                    .setName(node.getName()+node.getLastName())
                    .putExtra("disabled", SystemConstants.DISABLE.equals(node.getDelFlag()));
                treeNode.putExtra("geId", node.getGeId());
                treeNode.putExtra("geneName",node.getGeneName());
                treeNode.putExtra("gender",node.getGender());
                treeNode.putExtra("rankNo",node.getRankNo());
                treeNode.putExtra("spouseList", nameList.stream().filter(item -> item.getOtherId() != null && item.getOtherId().equals(node.getId())).collect(Collectors.toList()));
            }
        );
    }

    /**
     * 查询族谱族员树结构信息
     *
     * @param bo 族员信息
     * @return 族员树信息集合
     */
    @Override
    public NameTreeVo nameTreeList(GeNameBo bo) {
        LambdaQueryWrapper<GeName> lqw = buildQueryWrapper(bo);
        List<GeName> list = baseMapper.selectList(lqw);
        return buildNameTree(list);
    }

    /**
     * 构建前端所需要族谱树数据
     *
     * @param nameList 目录列表
     * @return 族谱树数据
     */
    @Override
    public NameTreeVo buildNameTree(List<GeName> nameList) {
        //获取顶级节点
        GeName root = nameList.stream().filter(item -> item.getParentId() == 0).findFirst().orElse(null);
        NameTreeVo vo = new NameTreeVo();
        if(root != null){
            List<GeName> childNodes = nameList.stream().filter(item -> item.getParentId() != null && item.getParentId().equals(root.getId())).toList();
            vo.setId(root.getId());
            vo.setName(root.getGeneName()+"世|"+root.getName() + root.getLastName());
            vo.setAvatar(StringUtils.isNotBlank(root.getAvatar())?root.getAvatar():baseUrl+"/avatar.png");
            vo.setImage_url(StringUtils.isNotBlank(root.getAvatar())?root.getAvatar():baseUrl+"/avatar.png");
            vo.setChildren(getChildNameTree(childNodes,nameList));
        }
        return vo;
    }

    @Override
    public boolean updateAvatar(Long nameId, Long avatar) {
        return baseMapper.update(null,new LambdaUpdateWrapper<GeName>().set(GeName::getAvatar, avatar).eq(GeName::getId, nameId))>0;
    }

    private List<NameTreeVo> getChildNameTree(List<GeName> childNodes,List<GeName> nameList){
        List<NameTreeVo> childList = Lists.newArrayList();
        if(CollUtil.isNotEmpty(childNodes)){
            for (GeName item : childNodes) {
                NameTreeVo vo = new NameTreeVo();
                vo.setId(item.getId());
                vo.setAvatar(StringUtils.isNotBlank(item.getAvatar())?item.getAvatar():baseUrl+"/avatar.png");
                vo.setName(item.getGeneName()+"世|"+item.getName() + item.getLastName());
                vo.setImage_url(StringUtils.isNotBlank(item.getAvatar())?item.getAvatar():baseUrl+"/avatar.png");
                List<GeName> childNodes1 = nameList.stream().filter(it -> it.getParentId() != null && it.getParentId().equals(item.getId())).toList();
                if (CollUtil.isNotEmpty(childNodes1)) {
                    vo.setChildren(getChildNameTree(childNodes1, nameList));
                }
                childList.add(vo);
            }
        }
        return childList;
    }
}
